package gpstools.track;

import gpstools.Location;
import gpstools.Location3D;
import gpstools.Points;
import gpstools.TrainingPoint;

import java.io.Serializable;

public class TrackPoint implements TrainingPoint, Serializable {
    private static final long serialVersionUID = 1L;

    private final TrackPointInfo info = new TrackPointInfo();

    private Location3D location;
    
    /** time in milliseconds */
    private Long time;

    /** heart rate in beats per minute */
    private Short heartRate;

    /** cadence in revolutions per minute */
    private Short cadence;

    /** power in watts */
    private Integer power;

    public Short getCadence() {
        return cadence;
    }

    public Integer getPower() {
        return power;
    }

    public Short getHeartRate() {
        return heartRate;
    }

    public Location3D getLocation() {
        return location;
    }

    public Long getTime() {
        return time;
    }

    private TrackPoint(Builder builder) {
        this.location = builder.location;
        this.time = builder.time;
        this.cadence = builder.cadence;
        this.power = builder.power;
        this.heartRate = builder.heartRate;
        this.info.setSpeedInMetersPerSecond(builder.speed);
    }

    public TrackPoint(TrainingPoint point) {
        this.location = point;
        this.time = point.getTime();
        this.cadence = point.getCadence();
        this.heartRate = point.getHeartRate();
    }

    public double distanceTo(Location other) {
        return Points.distance(this, other);
    }

    public boolean after(TrackPoint other) {
        return Points.after(this, other);
    }

    public static Builder builder(Location3D location) {
        return new Builder(location);
    }

    public double getLatitude() {
        return location.getLatitude();
    }

	public Double getElevation()
	{
        return location.getElevation();
    }

    public double getLongitude() {
        return location.getLongitude();
    }

    public static class Builder {
        private Location3D location;
        private Long time;
        private Short heartRate;
        private Short cadence;
        private Integer power;
        private Double speed;

        public Builder(Location3D location) {
            this.location = location;
        }

        public Builder time(Long time) {
            this.time = time;
            return this;
        }

        public Builder heartRate(Short hr) {
            this.heartRate = hr;
            return this;
        }

        public Builder cadence(Short cad) {
            this.cadence = cad;
            return this;
        }

        public Builder power(Integer power) {
            this.power = power;
            return this;
        }

        public TrackPoint build() {
            if (location == null) {
                throw new IllegalStateException("empty location");
            }
            return new TrackPoint(this);
        }

		public Builder speed(Double speed) {
			this.speed = speed;
			return this;
		}
    }
    
    public TrackPointInfo getInfo() {
		return info;
	}

    @Override
    public String toString() {
        return String.format("[%s, time=%s, heartRate=%s, cadence=%s]", location, time, heartRate, cadence);
    }

}
